<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>Power Management of Non-Virtualised Devices</title>
<meta name="author" content="Kevin Klues, Vlado Handziski, Jan-Hinrich Hauer, Phil Levis" />
<style type="text/css">

/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2009/02/03 23:07:32 $
:version: $Revision: 1.14 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/
body {
  font-family: Times;
  font-size: 16px;
}

.first {
  margin-top: 0 ! important }

.last {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1 {
  font-family: Arial, sans-serif;
  font-size: 20px;
}

h1.title {
 text-align: center;
 font-size: 32px;
}

h2 {
 font-size: 16px;
 font-family: Arial, sans-serif;
}

h2.subtitle {
  text-align: center }

h3 {
 font-size: 12px;
 font-family: Arial, sans-serif;
}

hr {
  width: 75% }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;
  background-color: #eeeeee;
  border-color: #000000;
  border-width: thin; 
  font-size: 14px
}

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em;
}

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap;
  }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

tt {}

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="power-management-of-non-virtualised-devices">
<h1 class="title">Power Management of Non-Virtualised Devices</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">TEP:</th><td class="field-body">115</td>
</tr>
<tr class="field"><th class="docinfo-name">Group:</th><td class="field-body">Core Working Group</td>
</tr>
<tr class="field"><th class="docinfo-name">Type:</th><td class="field-body">Documentary</td>
</tr>
<tr><th class="docinfo-name">Status:</th>
<td>Final</td></tr>
<tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">2.x</td>
</tr>
<tr><th class="docinfo-name">Author:</th>
<td>Kevin Klues, Vlado Handziski, Jan-Hinrich Hauer, Phil Levis</td></tr>
</tbody>
</table>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">This memo documents a part of TinyOS for the TinyOS Community, and
requests discussion and suggestions for improvements.  Distribution
of this memo is unlimited. This memo is in full compliance with TEP
1.</p>
</div>
<div class="section">
<h1><a id="abstract" name="abstract">Abstract</a></h1>
<p>This memo documents how TinyOS 2.x manages the power state of physical
(not virtualised) abstractions.</p>
</div>
<div class="section">
<h1><a id="introduction" name="introduction">1. Introduction</a></h1>
<p>TinyOS platforms have limited energy. A unified power management
strategy for all devices and peripherals is not feasible, as
they vary significantly in warm-up times, power profiles, and
operation latencies. While some devices, such as
microcontrollers, can efficiently calculate their lowest possible
power state very quickly, others, such as sensors with warm-up
times, require external knowledge to do so.</p>
<p>In TinyOS 1.x, applications are responsible for all power management.
Low-level subsystems, such as an SPI bus, are explicitly powered on
and off by higher level abstractions. This approach of deep calls
to <tt class="docutils literal"><span class="pre">StdControl.start()</span></tt> and <tt class="docutils literal"><span class="pre">StdControl.stop()</span></tt> introduces strange behaviors
and can get in the way of power conservation. Turning off the radio
on the Telos platform, for example, turns off the SPI bus and therefore
prevents the flash driver from working. Additionally, the microcontroller
stays in a higher power state for the SPI bus even when it is
inactive.</p>
<p>TinyOS 2.x defines two classes of devices for power-management:
microcontrollers and peripherals. TEP 112 documents how TinyOS 2.x
manages the power state of a microcontroller <a class="citation-reference" href="#tep112" id="id1" name="id1">[TEP112]</a>.
Unlike microcontrollers, which typically have several power states,
peripheral devices typically have two distinct states, <em>on</em> and <em>off</em>.
This TEP is dedicated to documenting how TinyOS 2.x controls the power
state of peripheral devices.</p>
<p>The term &quot;peripheral device&quot; refers to any hardware device which
arbitrates access with the mechanisms described in <a class="citation-reference" href="#tep108" id="id2" name="id2">[TEP108]</a> .  These
devices are not  virtualised in the sense that access to
them must be explicitly requested and released by their users.</p>
</div>
<div class="section">
<h1><a id="power-management-models" name="power-management-models">2. Power Management Models</a></h1>
<p>There are two different models to managing the power state of a
peripheral in TinyOS: <em>explicit power management</em> and <em>implicit
power management</em>.</p>
<p>The explicit model provides a means for a single client to manually
control the power state of a dedicated physical device (as defined by
<a class="citation-reference" href="#tep108" id="id3" name="id3">[TEP108]</a>).  Whenever this client tells the device to power up or down
it does so without delay (except for delays in the hardware of course).
This model
can be particularly useful when the control information driving the
selection of the proper power state of a device relies on external
logic contained in higher level components.  The following section
discusses the <tt class="docutils literal"><span class="pre">StdControl</span></tt>, <tt class="docutils literal"><span class="pre">SplitControl</span></tt>, and
<tt class="docutils literal"><span class="pre">AsyncStdControl</span></tt> interfaces used to perform power management of
this type.</p>
<p>The implicit model, on the other hand, provides a means for allowing
the power state of a device to be controlled from within the driver
for that device itself.  Device drivers following this model are never
explicitly powered up or down by some external client, but rather
<em>require</em> some internal policy to be defined that decides exactly when
their power states should be changed.  This policy could exist
natively on the hardware of the physical device itself, or be
implemented on top of some lower level abstraction of a physical
device adhering to the <em>explicit power management</em> model.</p>
<p>Shared devices (as defined by <a class="citation-reference" href="#tep108" id="id4" name="id4">[TEP108]</a>) can infer whether they
should be on or off based on the interfaces they provide to their
clients. For example, when a client requests the ADC, this implies
the ADC should be on; if there are no requests of the ADC, this implies
it should be off. Therefore shared devices do not need to provide a
power control interface. They can use an implicit power management policy.
Section 4.2 discusses this in more detail.:</p>
<pre class="literal-block">
               /|\                                    /|\
                |                                      |
          Data Interface                            Resource
                |                                      |
-----------------------------------------------------------------------
|             Shared Device (implicitly power managed)                |
-----------------------------------------------------------------------
               /|\                                    /|\
                |                                      |
          Data Interface                            Resource
                |                                      |
                |        ----------------------        |
                |        |    Power Manager   |        |
                |        ----------------------        |
                |          /|\            /|\          |
                |           |              |           |
                |      StdControl ResourceDefaultOwner |
                |           |              |           |
---------------------------------      --------------------------------
|        Dedicated Device       |      |            Arbiter           |
|  (explicitly power managed)   |      |                              |
---------------------------------      --------------------------------
</pre>
</div>
<div class="section">
<h1><a id="explicit-power-management" name="explicit-power-management">3. Explicit Power Management</a></h1>
<p>Just as in TinyOS 1.x, TinyOS 2.x has  <tt class="docutils literal"><span class="pre">StdControl</span></tt> and <tt class="docutils literal"><span class="pre">SplitControl</span></tt>
interfaces in order to control the on and off
power states of explicitly managed peripherals. TinyOS 2.x also
introduces a third interface, <tt class="docutils literal"><span class="pre">AsyncStdControl</span></tt>. A component
representing a hardware device that can be powered on and off MUST
provide one of these three interfaces.
The selection of the right interface depends on the
latencies involved in changing between these two states as well as the
nature of the code (sync or async) executing any of the interface's
commands.</p>
<div class="section">
<h2><a id="power-management-with-stdcontrol" name="power-management-with-stdcontrol">3.1 Power Management with <tt class="docutils literal"><span class="pre">StdControl</span></tt></a></h2>
<p>Whenever the powerup and powerdown times of a non-virtualised device
are negligible, they SHOULD provide the <tt class="docutils literal"><span class="pre">StdControl</span></tt> interface as
defined below:</p>
<pre class="literal-block">
interface StdControl {
  command error_t start();
  command error_t stop();
}
</pre>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">Powerup and powerdown times on the order of a few microseconds have
traditionally been considered negligible, and can be waited on using
one of the <em>BusyWait</em> interfaces described in <a class="citation-reference" href="#tep102" id="id5" name="id5">[TEP102]</a>.  Powerup
and powerdown times on the order of a few milliseconds, however,
should not be ignored, and MUST be hidden behind the use of the
<tt class="docutils literal"><span class="pre">SplitControl</span></tt> interface described later on in this section.
A general rule of thumb is that if waiting for powerup takes
more than one hundred microseconds, SplitControl is probably more
suitable.</p>
</div>
<p>An external component MUST call <tt class="docutils literal"><span class="pre">StdControl.start()</span></tt> to power a
device on and <tt class="docutils literal"><span class="pre">StdControl.stop()</span></tt> to power a device off.  Calls to
either command MUST return either SUCCESS or FAIL.</p>
<p>Upon the successful return of a call to <tt class="docutils literal"><span class="pre">StdControl.start()</span></tt>, a
device MUST be completely powered on, allowing calls to commands of other
interfaces implemented by the device to succeed.</p>
<p>Upon the successful return of a call to <tt class="docutils literal"><span class="pre">StdControl.stop()</span></tt>, a
device MUST be completely powered down, and any calls to commands
of other interfaces implemented by that device that actually access
the device hardware MUST return FAIL or EOFF.</p>
<p>If a device is not able to complete the <tt class="docutils literal"><span class="pre">StdControl.start()</span></tt> or
<tt class="docutils literal"><span class="pre">StdControl.stop()</span></tt> request for any reason, it MUST return FAIL.</p>
<p>Based on these specifications, the following matrix has been created
to describe the valid return values for any call made through the
<tt class="docutils literal"><span class="pre">StdControl</span></tt> interface in one of the devices valid power states:</p>
<table border="1" class="docutils">
<colgroup>
<col width="38%" />
<col width="31%" />
<col width="31%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Call</th>
<th class="head">Device On</th>
<th class="head">Device Off</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>StdControl.start()</td>
<td>SUCCESS</td>
<td>SUCCESS or FAIL</td>
</tr>
<tr><td>StdControl.stop()</td>
<td>SUCCESS or FAIL</td>
<td>SUCCESS</td>
</tr>
<tr><td>operation</td>
<td>depends</td>
<td>FAIL or EOFF</td>
</tr>
</tbody>
</table>
<p>Devices providing this interface would do so as shown below:</p>
<pre class="literal-block">
configuration DeviceC {
  provides {
    interface Init;
    interface StdControl;  //For Power Management
    ....
  }
}
</pre>
</div>
<div class="section">
<h2><a id="power-management-with-splitcontrol" name="power-management-with-splitcontrol">3.2 Power Management with <tt class="docutils literal"><span class="pre">SplitControl</span></tt></a></h2>
<p>When a device's powerup and powerdown times are non-negligible, the
<em>``SplitControl``</em> interface SHOULD be used in place of the <em>``StdControl``</em>
interface.  The definition of this interface can be seen below:</p>
<pre class="literal-block">
interface SplitControl {
  command error_t start();
  event void startDone(error_t error);
  command error_t stop();
  event void stopDone(error_t error);
}
</pre>
<p>An external component MUST call <tt class="docutils literal"><span class="pre">SplitControl.start()</span></tt> to power a
device on and <tt class="docutils literal"><span class="pre">SplitControl.stop()</span></tt> to power a device off.  Calls to
either command return one of SUCCESS, FAIL, EBUSY, or
EALREADY. SUCCESS indicates that the device has now started changing
its power state and will signal a corresponding completion event in
the future. EBUSY indicates that the device is in the midst of either starting
or stopping (e.g., it is starting when stop is called or stopping
when start is called) and will not issue an event. EALREADY indicates
that the device is already in that state; the call is erroneous and a
completion event will not be signaled. FAIL indicates that the
device's power state could not be changed. More explicitly:</p>
<p>Successful calls to <tt class="docutils literal"><span class="pre">SplitControl.start()</span></tt> MUST signal one of
<tt class="docutils literal"><span class="pre">SplitControl.startDone(SUCCESS)</span></tt> or <tt class="docutils literal"><span class="pre">SplitControl.startDone(FAIL)</span></tt>.</p>
<p>Successful calls to <tt class="docutils literal"><span class="pre">SplitControl.stop()</span></tt> MUST signal one of
<tt class="docutils literal"><span class="pre">SplitControl.stopDone(SUCCESS)</span></tt> or <tt class="docutils literal"><span class="pre">SplitControl.stopDone(FAIL)</span></tt>.</p>
<p>Upon signaling a <tt class="docutils literal"><span class="pre">SplitControl.startDone(SUCCESS)</span></tt>, a device MUST
be completely powered on, and operation requests through calls to commands
of other interfaces implemented by the device MAY succeed.</p>
<p>Upon signalling a <tt class="docutils literal"><span class="pre">SplitControl.stopDone(SUCCESS)</span></tt>, a device MUST be
completely powered down, and any subsequent calls to commands of other
interfaces implemented by the device that actually access
the device hardware MUST return EOFF or FAIL.</p>
<p>If a device is powered on and a successful call to <tt class="docutils literal"><span class="pre">SplitControl.stop()</span></tt>
signals a <tt class="docutils literal"><span class="pre">SplitControl.stopDone(FAIL)</span></tt>, the device MUST still be fully
powered on, and operation requests through calls to commands of other
interfaces implemented by the device MAY succeed.</p>
<p>If a device is powered down and a successful call to <tt class="docutils literal"><span class="pre">SplitControl.start()</span></tt>
signals a <tt class="docutils literal"><span class="pre">SplitControl.startDone(FAIL)</span></tt>, the device MUST still be fully
powered down, and operation requests through calls to commands of other
interfaces implemented by the device MUST return EOFF or FAIL.</p>
<p>If a device is not able to complete the <tt class="docutils literal"><span class="pre">SplitControl.start()</span></tt> or
<tt class="docutils literal"><span class="pre">SplitControl.stop()</span></tt> requests they MUST return FAIL.</p>
<p>Calls to either <tt class="docutils literal"><span class="pre">SplitControl.start()</span></tt> when the device is starting
or <tt class="docutils literal"><span class="pre">SplitControl.stop()</span></tt> while the device is stopping MUST return
SUCCESS, with the  anticipation that a corresponding
<tt class="docutils literal"><span class="pre">SplitControl.startDone()</span></tt> or <tt class="docutils literal"><span class="pre">SplitControl.stopDone()</span></tt>
will be signaled in the future.</p>
<p>Calls to <tt class="docutils literal"><span class="pre">SplitControl.start()</span></tt> when the device is started
or <tt class="docutils literal"><span class="pre">SplitControl.stop()</span></tt> while the device is stopped MUST
return EALREADY, indicating that the device is already in that
state. The corresponding completion event (startDone for start
or stopDone for stop) MUST NOT be signaled.</p>
<p>Calls to <tt class="docutils literal"><span class="pre">SplitControl.start()</span></tt> when the device is stopping or
<tt class="docutils literal"><span class="pre">SplitControl.stop()</span></tt> while the device is starting MUST return
EBUSY, indicating that the device is busy performing a differnet
operation. The correspodning completion event (startDone for start or
stopDone for stop) MUST NOT be signaled.</p>
<table border="1" class="docutils">
<colgroup>
<col width="34%" />
<col width="17%" />
<col width="18%" />
<col width="15%" />
<col width="15%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Call</th>
<th class="head">Device On</th>
<th class="head">Device Off</th>
<th class="head">Starting</th>
<th class="head">Stopping</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>SplitControl.start()</td>
<td>EALREADY</td>
<td>SUCCESS
FAIL</td>
<td>SUCCESS</td>
<td>EBUSY</td>
</tr>
<tr><td>SplitControl.stop()</td>
<td>SUCCESS
FAIL</td>
<td>EALREADY</td>
<td>EBUSY</td>
<td>SUCCESS</td>
</tr>
<tr><td>operation</td>
<td>depends</td>
<td>FAIL
EOFF
EOFF</td>
<td>FAIL
EOFF
SUCCESS</td>
<td>FAIL
EOFF</td>
</tr>
</tbody>
</table>
<p>Devices providing this interface would do so as shown below:</p>
<pre class="literal-block">
configuration DeviceC {
  provides {
    interface Init;
    interface SplitControl; \\ For Power Management
    ....
  }
}
</pre>
<div class="note">
<p class="first admonition-title">Note</p>
<p>Other approaches were considered for the return values of
<tt class="docutils literal"><span class="pre">SplitControl.start()</span></tt> and <tt class="docutils literal"><span class="pre">SplitControl.stop()</span></tt>.  One such
approach would have replaced EBUSY with SUCCESS when
<tt class="docutils literal"><span class="pre">SplitControl.start()</span></tt> was called while in the process of stopping
and <tt class="docutils literal"><span class="pre">SplitControl.stop()</span></tt> was called while in the process of starting.
However, implementing such an approach adds unwanted complexity to
a device driver.  It is unreasonable to expect the implementor of
each driver to implement this functionality.</p>
<p class="last">Returning EBUSY is the most straightforward, unambiguous value
that can be returned in such a situation.  By returning
EBUSY when a device is in a transitional state, the components
built on top of a driver unambiguously know exactly why a call to
<tt class="docutils literal"><span class="pre">start()</span></tt> or <tt class="docutils literal"><span class="pre">stop()</span></tt> did not succeed, and can take action accordingly.
Since only ONE component should ever implement the <tt class="docutils literal"><span class="pre">SplitControl</span></tt>
interface for a given device, it isn't unreasonable to expect them
to keep track of this return value themselves.  There is, of course,
nothing preventing someone from creating a component
on top of each driver implementation that implements things differently.</p>
</div>
</div>
<div class="section">
<h2><a id="power-management-with-asyncstdcontrol" name="power-management-with-asyncstdcontrol">3.3 Power Management with <tt class="docutils literal"><span class="pre">AsyncStdControl</span></tt></a></h2>
<p>The commands and the events of the <em>``StdControl``</em> and the <em>``SplitControl``</em>
interfaces are synchronous and can not be called from within
asynchronous code (such as interrupt service routines, etc.). For the
cases when the power state of the device needs to be controlled from
within asynchronous code, the <em>``AsyncStdControl``</em> interface MUST be used
in place of the <em>``StdControl``</em> interface.  The definition of this
interface can be seen below:</p>
<pre class="literal-block">
interface AsyncStdControl {
  async command error_t start();
  async command error_t stop();
}
</pre>
<p>All of the semantics that hold true for devices providing the
<tt class="docutils literal"><span class="pre">StdControl</span></tt> interface also hold for this interface.</p>
<p>Devices providing this interface would do so as shown below:</p>
<pre class="literal-block">
configuration DeviceC {
  provides {
    interface Init;
    interface AsyncStdControl; \\ For Power Management
    ....
  }
}
</pre>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">The <tt class="docutils literal"><span class="pre">AsyncStdControl</span></tt> interface should be provided whenever it might be
necessary to allow a device to be powered on or off while running in
async context.  If it is anticipated that a device <em>will</em> not (or more
likely <em>should</em> not) be powered on or off while in asynchronous context,
then the <tt class="docutils literal"><span class="pre">StdControl</span></tt> interface SHOULD be provided instead.  Components
that wish to power the device on or off from within async context would
then be required to post a task before doing so.  In practice,
<tt class="docutils literal"><span class="pre">AsyncStdControl</span></tt> is provided by low-level hardware resources, while
<tt class="docutils literal"><span class="pre">StdControl</span></tt> is provided by higher level services built on top of these
resources.</p>
</div>
</div>
</div>
<div class="section">
<h1><a id="implicit-power-management" name="implicit-power-management">4. Implicit Power Management</a></h1>
<p>While explicit power management provides the mechanism for changing
power states, it does not specify a policy.
This does not represent a large problem for the simple case
of <em>dedicated</em> devices, but can become crucial for non-trivial cases
involving complex interdependencies between devices controlled by multiple
clients.</p>
<p>For example, if component <em>A</em> is a client of both component <em>B</em>
and component <em>C</em>, what happens with <em>B</em> and <em>C</em> if
<tt class="docutils literal"><span class="pre">StdControl.stop()</span></tt> is called on component <em>A</em> ? Should components
<em>B</em> and <em>C</em> also be stopped?  What about the reverse case where both
<em>B</em> and <em>C</em> are clients of the single shared component, <em>A</em>?  If
devices <em>B</em> and <em>C</em> are shut off, should <em>A</em> be shut off as well?
How can one decide when it is appropriate to cascade such powerup
and powerdown requests?</p>
<p>The complex nature of the problem is evident from the number of
unexpected behaviors in TinyOS 1.x involving <tt class="docutils literal"><span class="pre">StdControl</span></tt>. On several
platforms, one of the SPI buses is shared between the radio and the
flash device. On some of them, issuing <tt class="docutils literal"><span class="pre">StdControl.stop()</span></tt> on the
radio results in a series of cascaded calls that result in SPI bus
becoming disabled, rendering the communication with the flash impossible.
Of course, the right policy would involve tracking the clients of the
SPI bus and powering it off only once both the radio and the flash
devices were no longer using it. Conversely, the SPI bus should be
powered on whenever there is at least one active client.</p>
<p>The selection of the right power management policy to use is a complex
task that depends on the nature of the devices in use, their
interdependency, as well as on any specific application requirements.
For cases when some of these features are known a-priori or are
restricted in some sense, it is preferable that the system provide
architectural support for enforcing a meaningful <em>default</em> power-management
policy instead of passing that task on to the application programmer to be
solved on a case-by-case basis.  The following section discusses these power
management policies and the components that implement them in greater detail.</p>
<div class="section">
<h2><a id="power-management-policies" name="power-management-policies">4.1. Power Management Policies</a></h2>
<p>Just as generic arbiters are offered in TinyOS 2.x to provide the
arbitration functionality required by shared resources, generic power
management policies are also offered to allow the power management of
non-virtualised devices to be automatically controlled.</p>
<p>Through the use of the arbiter components described in <a class="citation-reference" href="#tep108" id="id6" name="id6">[TEP108]</a>,
device drivers implemented as shared resources provide the type of
restricted resource interdependency where default power-management
policies can be offered. The shared resource class defined in Section
2.3 of <a class="citation-reference" href="#tep108" id="id7" name="id7">[TEP108]</a>, provides a well defined component interdependency,
where a single resource is shared among multiple clients. This
relationship enables the definition of default power-management
policies that can be used to automatically power the resource on and
off.</p>
<p>The <em>Power Manager</em> component implementing one of these polices acts as
the <em>default owner</em> of the shared resource device and interacts with it
through the use of the ResourceDefaultOwner interface:</p>
<pre class="literal-block">
interface ResourceDefaultOwner {
  async event void granted();
  async command error_t release();
  async command bool isOwner();
  async event void requested();
  async event void immediateRequested();
}
</pre>
<p>Acting as the default owner, the <em>Power Manager</em> waits for the
<tt class="docutils literal"><span class="pre">ResourceDefaultOwner.granted()</span></tt> event to be signaled in order to
gain ownership over the resource device.</p>
<p>Once it owns the device, the <em>Power Manager</em> is free to execute its
power-management policy using the StdControl-like interface provided by the
underlying resource. Different power managers can implement different
policies. In the simplest case, this would involve an immediate power-down
via one of the <tt class="docutils literal"><span class="pre">stop()</span></tt> commands. When the power-state transition
involves non-negligible costs in terms of wake-up latency or power
consumption, the <em>PowerManager</em> might revert to a more intelligent
strategy that tries to reduce these effects. As pointed out in the
introduction, one such strategy might involve the use of a timer to defer
the power-down of the resource to some later point in time, giving any
resource clients a window of opportunity to put in requests before the
device is fully shut down.</p>
<p>Regardless of the power management policy in use, the <em>Power Manager</em>
remains owner of the resource as long as the resource is not requested
by one of its clients.  Whenever a client puts in a request, the
<em>Power Manager</em> will receive a <tt class="docutils literal"><span class="pre">ResourceDefaultOwner.requested()</span></tt> event
(or <tt class="docutils literal"><span class="pre">immediateRequested()</span></tt> event) from the arbiter it is associated with.
Upon receiving this event, the <em>Power Manager</em> MUST power up the
resource through the StdControl-like interface provided by the lower level
abstraction of the physical device. The <em>Power Manager</em> MUST release the
ownership of the resource (using the <tt class="docutils literal"><span class="pre">ResourceDefaultOwner.release()</span></tt>
command) and MUST wait until after the resource has been fully powered on
before doing so.</p>
<p>Modeling devices as shared resources and allowing them to be
controlled in the way described here, solves the problems outlined in
section 3 regarding how to keep track of when and how the
powerdown of nested resources should proceed.  The <em>Power Manager</em>
component answers the question of how, and the combination of the power
management policy being used and the reception of the
<tt class="docutils literal"><span class="pre">ResourceDefaultOwner.granted()</span></tt> and <tt class="docutils literal"><span class="pre">ResourceDefaultOwner.requested()</span></tt>
events answers the question of when.  As long as the resource at
the bottom of a large set of nested resource clients has been fully released,
the power mananger will be able to power down the resource appropriately.</p>
<p>Using the model described above, a resource that uses one of these policies
according to the <em>implicitly power management</em> model could be built as shown below:</p>
<pre class="literal-block">
module MyFlashP {
  provides {
    interface Init;
    interface SplitControl;
    interface Resource;
    interface FlashCommands;
    ...
  }
}
implementation {
  ...
}

generic module PowerManagerC(uint8_t POWERDOWN_DELAY) {
  provides {
    interface Init;
  }
  uses {
    interface SplitControl;
    interface ResourceDefaultOwner;
  }
}
implementation {
  ...
}

#define MYFLASH_RESOURCE &quot;MyFlash.resource&quot;
#define MYFLASH_POWERDOWN_DELAY       1000
configuration MyFlashC {
  provides {
    interface Init;
    interface Resource;
    interface FlashCommands;
  }
}
implementation {
  components new PowerManagerC(MYFLASH_POWERDOWN_DELAY)
  , FcfsArbiter(MYFLASH_RESOURCE)
  , MyFlashP;

  Init = MyFlashP;
  Resource = FcfsArbiter;
  FlashCommands = MyFlashP;

  PowerManagerC.ResourceDefaultUser -&gt; FcfsArbiter;
  PowerManagerC.SplitControl -&gt; MyFlashP;

}
</pre>
<p>This example implementation is built out of three components.  The
first component (<tt class="docutils literal"><span class="pre">MyFlashP</span></tt>) follows the <em>explicit power management</em>
model for defining the interfaces to the physical flash device.  The
second component (<tt class="docutils literal"><span class="pre">PowerManagerC</span></tt>) is the generic <em>Power Manager</em>
component that will be used to implement the specific power management
policy for this device.  The third component (<tt class="docutils literal"><span class="pre">MyFlashC</span></tt>) is the
configuration file that wires together all of the components required
by the implementation of of the device as it adheres to the <em>implicit power
management</em> model.  It includes the <tt class="docutils literal"><span class="pre">MyflashP</span></tt> and <tt class="docutils literal"><span class="pre">PowerManagerC</span></tt>
components, as well as an arbiter component for managing shared clients
of the device.  Notice how the <em>Power Manager</em> is wired to both the
<tt class="docutils literal"><span class="pre">ResourceDefaultUser</span></tt> interface provided by the arbiter, and the
<tt class="docutils literal"><span class="pre">SplitControl</span></tt> interface provided by the flash.  All clients of this flash
device are directly connected to the resource interface provided by
the arbiter.  As outlined above, the <tt class="docutils literal"><span class="pre">PowerManagerC</span></tt> component will use
the events signaled through the <tt class="docutils literal"><span class="pre">ResourceDefaultUser</span></tt> interface to determine
when to make calls to power the device up and power it down through
the <tt class="docutils literal"><span class="pre">SplitControl</span></tt> interface.</p>
</div>
<div class="section">
<h2><a id="example-power-managers-powermanagerc-and-deferredpowermanagerc" name="example-power-managers-powermanagerc-and-deferredpowermanagerc">4.2. Example Power Managers: PowerManagerC and DeferredPowerManagerC</a></h2>
<p>TinyOS 2.x currently has two default power management policies
that it provides.  These policies are implemented by the various
components located under tinyos-2.x/lib/power. The first policy
is implemented using an <em>immediate</em> power control scheme, whereby
devices are powered on and off immediately after they have been
requested and released.  The second policy is implemented using
a <em>deferred</em> power control scheme, whereby devices are powered
on immediately after being requested, but powered off after
some small delay from being released. This delay is configurable
to meet the varying needs of different device drivers.</p>
<p>Each policy has three different implementations for use by each of
the <tt class="docutils literal"><span class="pre">StdControl</span></tt>, <tt class="docutils literal"><span class="pre">SplitControl</span></tt>, and <tt class="docutils literal"><span class="pre">AsyncStdControl</span></tt>
interfaces.</p>
<p>For reference, each of the available components are listed below</p>
<dl class="docutils">
<dt>Immediate Power Management:</dt>
<dd><ul class="first last simple">
<li><tt class="docutils literal"><span class="pre">StdControlPowerManagerC</span></tt></li>
<li><tt class="docutils literal"><span class="pre">SplitControlPowerManagerC</span></tt></li>
<li><tt class="docutils literal"><span class="pre">AsyncStdControlPowerManagerC</span></tt></li>
</ul>
</dd>
<dt>Deferred Power Management:</dt>
<dd><ul class="first last simple">
<li><tt class="docutils literal"><span class="pre">StdControlDeferredPowerManagerC</span></tt></li>
<li><tt class="docutils literal"><span class="pre">SplitControlDeferredPowerManagerC</span></tt></li>
<li><tt class="docutils literal"><span class="pre">AsyncStdControlDeferredPowerManagerC</span></tt></li>
</ul>
</dd>
</dl>
</div>
</div>
<div class="section">
<h1><a id="author-s-address" name="author-s-address">5. Author's Address</a></h1>
<div class="line-block">
<div class="line">Kevin Klues</div>
<div class="line">444 Gates Hall</div>
<div class="line">Stanford University</div>
<div class="line">Stanford, CA 94305-9030</div>
<div class="line"><br /></div>
<div class="line">email - <a class="reference" href="mailto:klueska&#64;cs.stanford.edu">klueska&#64;cs.stanford.edu</a></div>
<div class="line"><br /></div>
<div class="line">Vlado Handziski</div>
<div class="line">Sekr FT5</div>
<div class="line">Einsteinufer 25</div>
<div class="line">10587 Berlin</div>
<div class="line">GERMANY</div>
<div class="line"><br /></div>
<div class="line">phone - +49 30 314 23831</div>
<div class="line">email - <a class="reference" href="mailto:handzisk&#64;tkn.tu-berlin.de">handzisk&#64;tkn.tu-berlin.de</a></div>
<div class="line"><br /></div>
<div class="line">Jan-Hinrich Hauer</div>
<div class="line">Sekr FT5</div>
<div class="line">Einsteinufer 25</div>
<div class="line">10587 Berlin</div>
<div class="line">GERMANY</div>
<div class="line"><br /></div>
<div class="line">phone - +49 30 314 23813</div>
<div class="line">email - <a class="reference" href="mailto:hauer&#64;tkn.tu-berlin.de">hauer&#64;tkn.tu-berlin.de</a></div>
<div class="line"><br /></div>
<div class="line">Philip Levis</div>
<div class="line">358 Gates Hall</div>
<div class="line">Stanford University</div>
<div class="line">Stanford, CA 94305-9030</div>
<div class="line"><br /></div>
<div class="line">phone - +1 650 725 9046</div>
<div class="line">email - <a class="reference" href="mailto:pal&#64;cs.stanford.edu">pal&#64;cs.stanford.edu</a></div>
</div>
</div>
<div class="section">
<h1><a id="citations" name="citations">6. Citations</a></h1>
<table class="docutils citation" frame="void" id="tep102" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id5" name="tep102">[TEP102]</a></td><td>TEP 102: Timers.</td></tr>
</tbody>
</table>
<table class="docutils citation" frame="void" id="tep108" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="tep108">[TEP108]</a></td><td><em>(<a class="fn-backref" href="#id2">1</a>, <a class="fn-backref" href="#id3">2</a>, <a class="fn-backref" href="#id4">3</a>, <a class="fn-backref" href="#id6">4</a>, <a class="fn-backref" href="#id7">5</a>)</em> TEP 108: Resource Arbitration.</td></tr>
</tbody>
</table>
<table class="docutils citation" frame="void" id="tep112" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1" name="tep112">[TEP112]</a></td><td>TEP 112: Microcontroller Power Management.</td></tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
